/*
 * Copyright (C) 2012-2013  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.remote.topology;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import nemos.remote.util.EplEndpointProvider;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.EndpointListener;
import org.osgi.service.remoteserviceadmin.ExportReference;
import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent;
import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener;

/**
 * LocalEndpointProvider : The local endpoints provider service.
 * 
 * <p>
 * This service listens to the remote service admin events and notifies the
 * {@link EndpointListener}s. It handles the multiple registrations of a single
 * {@link ExportReference} and notifies only for the first successfull
 * registration and the last unregistration of an endpoint.
 * </p>
 * 
 * <p>
 * It provides only local endpoints, remote ones are handled by the dicovery
 * bundle(s).
 * </p>
 * 
 * @author Romain DUBOIS
 */
@Service(RemoteServiceAdminListener.class)
@Component
public class LocalEndpointProvider extends EplEndpointProvider implements
        RemoteServiceAdminListener {

    /** The export references with the original endpoint */
    private final Map<ExportReference, EndpointDescription> mLocalEndpoints;

    /**
     * Constructor
     */
    public LocalEndpointProvider() {
        super();

        mLocalEndpoints = Collections
                .synchronizedMap(new HashMap<ExportReference, EndpointDescription>());
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener#remoteAdminEvent(org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent)
     */
    @Override
    public void remoteAdminEvent(final RemoteServiceAdminEvent pEvent) {
        final ExportReference lReference = pEvent.getExportReference();
        if (lReference != null) {

            EndpointDescription lDescription = null;
            if (pEvent.getType() == RemoteServiceAdminEvent.EXPORT_REGISTRATION) {

                // Minimize the synchronized code
                synchronized (mLocalEndpoints) {
                    if (mLocalEndpoints.get(lReference) == null) {
                        lDescription = lReference.getExportedEndpoint();
                        mLocalEndpoints.put(lReference, lDescription);
                    }
                }
            } else if (pEvent.getType() == RemoteServiceAdminEvent.EXPORT_UNREGISTRATION) {

                // Check if service is no longer exported
                if (lReference.getExportedEndpoint() == null) {
                    lDescription = mLocalEndpoints.remove(lReference);
                }
            }

            // Notify endpoint listeners
            if (lDescription != null) {
                notifyListeners(lDescription,
                        pEvent.getType() == RemoteServiceAdminEvent.EXPORT_REGISTRATION);
            }
        }
    }
}
